<template>
    <div>
        <h4>基础篇-侦听器</h4>
        <div>详情查看控制台</div>

        <button @click="btn">修改</button>
    </div>
</template>

<script setup>
import { reactive, ref, watch, watchEffect, watchPostEffect, watchSyncEffect } from 'vue';

// 简单数据
let count = ref(1)
// 复杂类型
let info = reactive({ name: 'zhangsan', age: 20 })

const btn = () => {
    count.value++
    info.name = "Hello"
    info.age = info.age + count.value
}

/**
 * watchEffect()
 * 【说明】：自动侦听回调函数中使用响应式数据，并在他们发生变化时立即执行回调
 * 【特点】：自动收集依赖、不需要指定侦听目标
 *          立即执行执行一次
 *          在组件更新前执行
 */
watchEffect(() => {
    console.log("watchEffect", count.value, info);
})



/**
 * watchPostEffect()
 * 【说明】：与 watchEffect 类似，但是会在组件更新后执行、其他与watchEffect一致
 * 【特点】：
 */
watchPostEffect(() => {
    console.log("watchPostEffect", count.value, info);
})


/**
 * watchSyncEffect()
 * 【说明】：与 watchEffect 类似，但回调会同步执行（在依赖变化后立即执行，不等待队列）
 * 【特点】：
 */
watchSyncEffect(() => {
    console.log("watchSyncEffect", count.value, info);
})


/**
 * watch 
 * 【说明】：显示监听一个或多个响应式数据源、watch 属于懒侦听、只有在数据发生变化后才会执行回调函数
 *  参数一：监听目标、可以是不同的数据源、例如ref reactive 计算属性 getter函数 数组等
 *  参数二：回调函数、回调函数中的参数 newVal 数据发生变化后 oldVal 数据发生变化前
 *  参数三：配置项：immediate:true 表示侦听器创建后立即侦听
 *                 deep:true 表示进行深度侦听、在watch 默认帮助我们进行深度侦听、可以不配置
 *                 once: true 表示只侦听一次
 */

// 1、侦听 ref 基本数据类型
watch(count, (newVal, oldVal,) => {
    console.log("侦听 ref 基本数据类型", newVal, oldVal)
},)

// // 2、侦听 reactive 复杂数据类型
watch(info, (newVal, oldVal,) => {
    console.log("侦听 reactive 复杂数据类型", newVal, oldVal)
},)

// // 3、侦听reactive 数据返回 一个普通的对象
watch(() => ({ ...info }), (newVal, oldVal) => {
    console.log("侦听reactive 数据返回 一个普通的对象", newVal, oldVal)
})

// // 4、侦听多个数据、将多个数据放入一个数组中作为参数进行侦听
watch([count, { ...info }], (newVal, oldVal) => {
    console.log("侦听多个数据、将多个数据放入一个数组中作为参数进行侦听", newVal, oldVal)
})



/**
 * 停止侦听、暂停侦听 用于 watch、watchEffect
 */
// const { stop } = watchEffect(() => {
//     console.log(count.value)
// })
// setTimeout(() => {
//     console.log('停止侦听...');
//     stop() // 停止侦听 返回的这个方法、调用这个方法即可实现侦听器的停止侦听
// }, 2000)

</script>

<style lang="scss" scoped></style>